var path = require('path')
var fs = require('fs')
var browserify = require('rebrowser')
var debug = require('debug')('rebrowser-watcher')

var compressSet = false;

//if state equal 1, source code is compressed in combined package
exports.setCompressState = function(state){
    compressSet = state == 1;
};
//
// Takes a path to a js file, outputs browserified version, e.g.
// dir/filename.js -> dir/filename.run.js
// cb: callback,First @param define rows that should have included in this app file
// excludeSet, define rows that should be excluded in global row set
//
exports.combineWatcher = function(jsfiles, cb, excludeMap) {
  if (typeof jsfiles == 'string') jsfiles = [ jsfiles ]
  jsfiles = indistinctMatch(jsfiles)
  var bundles = [];
  jsfiles.forEach(function(mainjs) {
    debug('processing', mainjs)
    var b = browserify(mainjs, excludeMap, compressSet)
    bundles.push(b);
    /**
     * 多一层文件夹 run 目录，名称后缀改为 .run.js
     * */
    var newname = path.basename(mainjs, '.js') + '.run.js'
    var fdirname = path.dirname(mainjs) + "/run/"
    //需合包的文件目录下 run目录 是否存在, 不存在则创建
    if(!fs.existsSync(fdirname)){
        fs.mkdir(fdirname)
    }
    var output = path.join(fdirname, newname)
    var prettypath = path.relative(path.dirname(module.parent.filename), output)

    // regen on change
    // TODO detect renames
    var seen = {}
    b.on('file', function(file, id, parent) {
      if (seen[file] || (excludeMap && excludeMap[file])){
          return
      }
      seen[file] = true;
      //log("watch file " + file);
      /** 改动某个include文件时时会陷入重写的死循环吗*/
      fs.unwatchFile(file)
      fs.watchFile(file, { persistent: true, interval: 507} ,function(curr, prev) {
        //debug('`'+ e + '` event on',  file)
        //log( 'event on', curr.mtime, prev.mtime)
        //want to be notified when the file was modified, not just accessed, compare curr.mtime and prev.mtime
        if(curr.mtime.getTime() > prev.mtime.getTime()){
            bundle(b)
        }
      })
    })

    // force-regen on startup
    bundle(b)

    function bundle(b) {
      b.bundle(onBundle).on('error', onErr)
    }
    function onBundle(err, src, fileIDMap) {
      if (err) log(err.stack)
      fs.writeFile(output, src, 'utf8', onWrite);
      if(cb){
          cb(fileIDMap);
      }
      //console.log("watcher file set:" + fileSet.join(","));
    }
    function onWrite (err) {
      if (err) log(err.stack)
      log(new Date().toLocaleTimeString(), 'updated', prettypath)
    }
  })
  return bundles;
}

// indistinct matching for any filename in a directory
function indistinctMatch(jsfiles){
    var resfiles = []
    jsfiles.forEach(function(currjs) {
        var fidx = currjs.lastIndexOf("/")
        var sidx = currjs.lastIndexOf("*")
        if(fidx >= sidx){
            resfiles.push(currjs)
            return
        }
        var currdir = currjs.substring(0, fidx + 1)
        var currsuf = currjs.substr(sidx + 1)
        var filelist = fs.readdirSync(currdir)
        filelist.forEach(function(mjs){
            if(mjs.substr(- currsuf.length) === currsuf){
                resfiles.push(currdir + mjs)
            }
        })
    })
    return resfiles
}

function onErr(err) {
  log(err.stack)
}

function log() {
  var args = [].slice.call(arguments)
  console.log.apply(console, ['browserify-watcher:'].concat(args))
}
